package spring.fox.bean;

import spring.fox.annotation.RpcService;
import fox.framework.rpc.context.definition.AbstractRpcDefinition;
import fox.framework.rpc.context.definition.RpcDefinitionBuilder;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import spring.fox.config.RpcBeanConfig;
import spring.fox.context.SpringFoxRpcObjectFactory;

/**
 * @author cuichao
 * @Description: RpcServiceBean
 * @Date: create in 2021/3/13 21:58
 */
public class RpcServiceBean extends RpcBeanConfig implements BeanNameAware ,InitializingBean ,BeanFactoryAware {

    public static final String RPC_SERVICE_SOURCE_BEAN_REF = "serviceRef";

    public static final String RPC_SERVICE_SOURCE_BEAN_NAME = "sourceName";

    /**
     * Rpc-Source-Bean-Instance
     */
    private Object serviceRef;
    /**
     * RpcService 注解实例
     */
    private RpcService annotation;
    /**
     *Rpc-Source-Bean-Name
     */
    private String sourceName;
    /**
     *Rpc-BeanName
     */
    private String beanName;


    private ConfigurableListableBeanFactory beanFactory;



    /**
     * 构建RpcDefinition
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(sourceName);
        RpcDefinitionBuilder builder = RpcDefinitionBuilder.genericRpcDefinition();
        builder.setMetaspace(beanName);
        builder.setServiceInterface(getRpcServiceInterface());
        builder.setProvider(true);
        AbstractRpcDefinition definition = builder.getDefinition();
        beanDefinition.setAttribute(SpringFoxRpcObjectFactory.RPC_DEFINITION_KEY, definition);
    }



    public RpcServiceBean(RpcService annotation) {
        this.annotation = annotation;
    }


    public Object getRpcService() {
        return serviceRef;
    }


    public Class<?> getRpcServiceInterface() {
        if (AopUtils.isAopProxy(serviceRef)) {
            return AopUtils.getTargetClass(serviceRef);
        }
        return serviceRef.getClass();
    }

    public void setServiceRef(Object bean) {
        this.serviceRef = bean;
    }

    public void setSourceName(String sourceName) {
        this.sourceName = sourceName;
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }


    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
            throw new IllegalArgumentException(
                    this.getClass().getSimpleName() + " requires a ConfigurableListableBeanFactory: " + beanFactory);
        }
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }
}
